<?php
// -----------------------------------------------------------------------------
// include
// -----------------------------------------------------------------------------

include "config/config.php";
include "auth.php";
include "DBManager.php";
require __DIR__ . '/vendor/autoload.php';

use Overtrue\ChineseCalendar\Calendar;

// -----------------------------------------------------------------------------
// 数据库相关设置
// -----------------------------------------------------------------------------

$db = new DBManager("sqlite:" . $dbPath);

// -----------------------------------------------------------------------------
// 函数定义
// -----------------------------------------------------------------------------

/**
 * 传入一个纯文本字符串，返回一个 html 字符串
 * @param string $content
 * @return false|string
 */
function textToHtml(string $content) {

    if (empty(trim($content))) {
        return false;
    } else {

        $content = rtrim($content);
        $str = str_replace(PHP_EOL, "<br />", $content);
        $arr = explode("<br />", $str);
        $result = "";
        $hrMinus = "<hr style='height 1px; border: 0; border-top: 2px dashed gray; margin-top: 4px; margin-bottom: 4px;' />";
        $hrEqual = "<hr style='height 1px; border: 0; border-top: 3px dashed darkorange; margin-top: 4px; margin-bottom: 4px;' />";

        foreach ($arr as $item) {

            $item = trim($item);

            if (empty($item) || $item == "\r") {

                $result .= "<br />";

            } elseif ($item == "暂无。") {

                $result .= $item;
                $result .= "<br />";

            } elseif ($item[0] == "=" || $item[0] == "-") {
                // 以 = 或 - 开头

                if (empty(ltrim($item, "="))) {
                    // 全部由 = 组成

                    $item = $hrEqual;
                    $result .= $item;

                } elseif (empty(ltrim($item, "-"))) {
                    // 全部由 - 组成

                    $item = $hrMinus;
                    $result .= $item;

                } else {

                    $result .= <<<BBB
                        <input class="taskItem" type="checkbox" />
                        <span class="taskTitle" role="button">$item</span>
                        <br />
                    BBB;

                }

            } elseif ($item[0] == "#") {
                // 以 # 开头

                $lengthOfItemOld  = strlen($item); // item 字符串的长度，移除左侧 # 符号前的
                $item = ltrim($item, "#"); // 移除左侧的 # 符号
                $lengthOfItemNew = strlen($item); // item 字符串的长度，移除左侧 # 符号后的
                $number = $lengthOfItemOld - $lengthOfItemNew; // 代表着有多少个 # 符号被移除

                if (empty(trim($item))) {
                    // 移除左侧 # 符号后，什么字符都不剩下，或者只剩下了空格

                    $item = "<br />";

                } else {

                    if (empty(trim(str_replace("=", "", $item)))) {
                        // 「# ======」

                        $item = $hrEqual;

                    } elseif (empty(trim(str_replace("-", "", $item)))) {
                        // 「# ------」

                        $item = $hrMinus;

                    } else {

                        if ($number == 1) {

                            $item = "<h5 class='fw-bold'>◆ {$item}</h5>";

                        } else {

                            $item = "<h6 class='fw-bold'>◇ {$item}</h6>";

                        }

                    }

                }

                $result .= $item;

            } else {

                // 判断待办事项中是否包含中文或英文感叹号
                $count = substr_count($item, "!") + substr_count($item, "！");
                if ($count > 0) {
                    if ($count < 3) {
                        $item = "<span class='text-info'>" . $item . "</span>";
                    } else {
                        $item = "<span class='text-danger'>" . $item . "</span>";
                    }
                } else {
                    // 判断待办事项中是否包含中文或英文问号
                    // 如果同时有叹号和问号，不论哪个在前哪个在后，都以叹号为准。
                    $count = substr_count($item, "?") + substr_count($item, "？");
                    if ($count > 0) {
                        $item = "<span class='text-muted fw-lighter'>" . $item . "</span>";
                    } else {
                        $item = "<span class='text-dark'>" . $item . "</span>";
                    }
                }

                $result .= <<<BBB
                    <input class="taskItem" type="checkbox" />
                    <span class="taskTitle" role="button">$item</span>
                    <br />
                BBB;

            }
        }
        return $result;

    }

}

// -----------------------------------------------------------------------------
// 时间日期相关设置
// -----------------------------------------------------------------------------

/* 设置时区 */

date_default_timezone_set($region);

/* 取得 the 日期 of 今日 */

$todayObj = new DateTime("today");
$todayStr = $todayObj->format("Ymd");

/* 取得 the 日期 of 明日 */

$tomorrowObj = new DateTime("tomorrow");
$tomorrowStr = $tomorrowObj->format("Ymd");

// -----------------------------------------------------------------------------
// 访问设置
// -----------------------------------------------------------------------------

if (!isset($_GET['date'])) {
    exit("需要指定有效的日期。");
}

$date = htmlspecialchars($_GET['date']);

if ($date == "undefinedundefined") {
    exit("无效的日期。");
}

if ($date == "today") {
    $date = $todayStr;
}

if ($date == "tomorrow") {
    $date = $tomorrowStr;
}

// -----------------------------------------------------------------------------

/* 取得 the 日期 that 用户指定的 */

$specificDateObj = new DateTimeImmutable($date);
$specificDateStr = $specificDateObj->format("Ymd");

$year            = $specificDateObj->format("Y"); // 年
$month           = $specificDateObj->format("m"); // 月
$dayOfMonth      = $specificDateObj->format("d"); // 日
$dayOfWeek       = $specificDateObj->format("w"); // 星期几
$monthAndDay     = $month . $dayOfMonth;          // 阳历 monthAndDay

// -----------------------------------------------------------------------------

/* 取得 the 农历 monthAndDay of the 日期 that 用户指定的 */

$calendar = new Calendar();
$result = $calendar->solar($year, $month, $dayOfMonth);

$animal = ""; // 生肖
if (isset($result["animal"])) {
    $animal = $result["animal"];
}

$jieqi = ""; // 节气
if (isset($result["term"])) {
    $jieqi = $result["term"];
    $jieqi = "| <a href='https://cn.bing.com/search?q=节气+{$jieqi}'>$jieqi</a>";
}

$isLeap = ""; // 是否为闰月
if ($result["is_leap"] == true) {
    $isLeap = "-";
}

$monthLunar              = $result["lunar_month"]; // 农历月，数字，形如：01
$dayOfMonthLunar         = $result["lunar_day"];   // 农历天，数字，形如：21

$monthLunarChinese       = $result["lunar_month_chinese"]; // 农历月，汉字，形如：正月
$dayOfMonthLunarChinese  = $result["lunar_day_chinese"];   // 农历天，汉字，形如：廿一

$monthAndDayLunar        = $isLeap . $monthLunar . $dayOfMonthLunar;     // 农历 monthAndDay，数字，形如：0121, -0121
$monthAndDayLunarChinese = $monthLunarChinese . $dayOfMonthLunarChinese; // 农历 monthAndDay，汉字，形如：正月廿一，闺正月廿一

// -----------------------------------------------------------------------------

/* 获取 the 日期 before 指定日期 */

$preDayObj = $specificDateObj->sub(new DateInterval("P1D"));
$preDayStr = $preDayObj->format("Ymd");

// -----------------------------------------------------------------------------

/* 获取 the 日期 after 指定日期 */

$nextDayObj = $specificDateObj->add(new DateInterval("P1D"));
$nextDayStr = $nextDayObj->format("Ymd");

// -----------------------------------------------------------------------------

$contents = [];
$contents["specificDate"] = $db->readFromSpecificDate($specificDateStr); // 日程 - 指定日
$contents["yearly"]       = $db->readFromYearly($monthAndDay);           // 日程 - 每年 - 阳历
$contents["yearlyLunar"]  = $db->readFromYearlyLunar($monthAndDayLunar); // 日程 - 每年 - 农历
$contents["monthly"]      = $db->readFromMonthly($dayOfMonth);           // 日程 - 每月 - 阳历
$contents["monthlyLunar"] = $db->readFromMonthlyLunar($dayOfMonthLunar); // 日程 - 每月 - 农历
$contents["weekly"]       = $db->readFromWeekly($dayOfWeek);             // 日程 - 每周
$contents["daily"]        = $db->readFromDaily();                        // 日程 - 每日

// -----------------------------------------------------------------------------
// 在HTML输出前初始化所有状态变量，解决变量未定义问题
// -----------------------------------------------------------------------------

// 初始化所有内容状态变量
$contentOfSpecificDateEmpty = true;
$contentOfYearlyLunarEmpty  = true;
$contentOfMonthlyLunarEmpty = true;
$contentOfYearlyEmpty       = true;
$contentOfMonthlyEmpty      = true;
$contentOfWeeklyEmpty       = true;
$contentOfDailyEmpty        = true;

// 计算每个分类的内容是否为空
$contentOfSpecificDateEmpty = !textToHtml($contents['specificDate']);
$contentOfYearlyLunarEmpty  = !textToHtml($contents['yearlyLunar']);
$contentOfMonthlyLunarEmpty = !textToHtml($contents['monthlyLunar']);
$contentOfYearlyEmpty       = !textToHtml($contents['yearly']);
$contentOfMonthlyEmpty      = !textToHtml($contents['monthly']);
$contentOfWeeklyEmpty       = !textToHtml($contents['weekly']);
$contentOfDailyEmpty        = !textToHtml($contents['daily']);

// 准备侧边栏菜单项数据
$sidebarItems = [
    [
        'id' => 'specificDate',
        'number' => '1',  // 单独的序号字段
        'title' => '当日',  // 移除标题中的序号
        'empty' => $contentOfSpecificDateEmpty,
        'iconEmpty' => 'bi-calendar-check',
        'iconFilled' => 'bi-calendar-check-fill'
    ],
    [
        'id' => 'yearlyLunar',
        'number' => '2',
        'title' => "农历每年",
        'empty' => $contentOfYearlyLunarEmpty,
        'iconEmpty' => 'bi-calendar-check',
        'iconFilled' => 'bi-calendar-check-fill'
    ],
    [
        'id' => 'monthlyLunar',
        'number' => '3',
        'title' => "农历每月",
        'empty' => $contentOfMonthlyLunarEmpty,
        'iconEmpty' => 'bi-calendar-check',
        'iconFilled' => 'bi-calendar-check-fill'
    ],
    [
        'id' => 'yearly',
        'number' => '4',
        'title' => "阳历每年",
        'empty' => $contentOfYearlyEmpty,
        'iconEmpty' => 'bi-calendar-check',
        'iconFilled' => 'bi-calendar-check-fill'
    ],
    [
        'id' => 'monthly',
        'number' => '5',
        'title' => "阳历每月",
        'empty' => $contentOfMonthlyEmpty,
        'iconEmpty' => 'bi-calendar-check',
        'iconFilled' => 'bi-calendar-check-fill'
    ],
    [
        'id' => 'weekly',
        'number' => '6',
        'title' => "每周",
        'empty' => $contentOfWeeklyEmpty,
        'iconEmpty' => 'bi-calendar-check',
        'iconFilled' => 'bi-calendar-check-fill'
    ],
    [
        'id' => 'daily',
        'number' => '7',
        'title' => '每日',
        'empty' => $contentOfDailyEmpty,
        'iconEmpty' => 'bi-calendar-check',
        'iconFilled' => 'bi-calendar-check-fill'
    ]
];


// -----------------------------------------------------------------------------
?>
<html lang="zh">
<head>
    <meta charset="utf-8">
    <title>Todo - <?php echo $specificDateStr; ?></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="stylesheet" href="resources/bootstrap-5.2.0-beta1-dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="resources/bootstrap-icons/bootstrap-icons.css">
    <style>
        a {
            text-decoration: none;
        }
        .big {
            font-size: large;
        }
        h5 {
            margin-top: 4px;
            margin-bottom: 4px;
        }
        h6 {
            margin-top: 4px;
            margin-bottom: 4px;
        }
        .fixed-top {
            position: fixed;
            top: 0;
            right: 0;
            left: 0;
            z-index: 1030;
        }
        .todoList {
        }
        .taskItem {
            cursor: pointer;
        }
        .taskTitle:hover {
            transform: scale(1.2); /* 放大到原来的1.2倍 */
            /* 可选：添加其他样式增强效果 */
            font-weight: bold;
            color: #2c3e50;
        }
        main {
            padding-top: 43px;
        }
        /* 侧边栏菜单样式 */
        .sidebar {
            position: fixed;
            top: 56px; /* 与顶部导航栏高度一致 */
            bottom: 0;
            left: 0;
            z-index: 1020;

            height: calc(100vh - 48px);
            overflow-x: hidden;
            overflow-y: auto; /* 内容过长时可滚动 */

            padding: 0;

            background-color: #ffffff; /* 与悬浮菜单背景色统一 */
            box-shadow: 2px 0 8px rgba(0, 0, 0, 0.04); /* 与悬浮菜单阴影风格匹配 */
            border-right: 1px solid #f1f1f1; /* 浅色边框 */
        }

        /* 侧边栏菜单容器 */
        .sidebar-menu {
            padding: 0;
            margin: 0;
            list-style: none;
        }

        /* 基础项样式 - 空项和非空项共有的样式 */
        .sidebar-item {
            display: flex;
            align-items: center;
            padding: 12px 20px;
            color: #495057; /* 基础文字色 */
            text-decoration: none;
            border-bottom: 1px solid #f1f1f1; /* 分隔线 */
            transition: all 0.2s ease;
            cursor: pointer; /* 手型光标 */
            border-left: 3px solid transparent; /* 预留给活动状态的左边框空间 */
            justify-content: space-between; /* 主内容与序号两端对齐 */
            position: relative;
        }

        /* 图标基础样式 - 空项和非空项共有 */
        .sidebar-item i {
            width: 24px;
            margin-right: 10px;
            text-align: center;
            transition: transform 0.2s ease;
        }

        /* 悬停时图标动画 - 空项和非空项共有 */
        .sidebar-item:hover i {
            transform: scale(1.1); /* 与悬浮菜单交互反馈一致 */
        }


        /* -------------------------- 空项样式 -------------------------- */

        /* 空项非活动状态 */
        .sidebar-item:not(.has-content):not(.active) {
            background-color: transparent; /* 继承侧边栏背景色 */
            color: #495057; /* 深灰文字 */
        }

        /* 空项悬停效果 */
        .sidebar-item:not(.has-content):hover:not(.active) {
            background-color: #f8f9fa; /* 与悬浮菜单项hover背景一致 */
            color: #28a745; /* 主色调强调 */
        }

        /* 空项活动状态 */
        .sidebar-item:not(.has-content).active {
            border-left: 4px solid #0d6efd; /* 与悬浮菜单点击痕迹同色 */
            color: #0d6efd; /* 活动状态文字色，与边框呼应 */
            font-weight: 500;
            /* 不改变背景色，保持与非活动状态的连贯性 */
        }

        /* -------------------------- 非空项样式 -------------------------- */

        /* 非空项非活动状态 */
        .sidebar-item.has-content:not(.active) {
            background-color: #fff1cc; /* 与悬浮菜单非空项背景协调 */
            color: #856404; /* 黄色系文字，增强可读性 */
        }

        /* 非空项悬停效果 */
        .sidebar-item.has-content:hover:not(.active) {
            background-color: #f4dc8d; /* 更深的黄色hover效果 */
            color: #28a745; /* 主色调强调 */
        }

        /* 非空项活动状态 */
        .sidebar-item.has-content.active {
            border-left: 4px solid #0d6efd; /* 与悬浮菜单点击痕迹同色 */
            background-color: #fff1cc; /* 与悬浮菜单非空项背景协调 */
            color: #0d6efd; /* 活动状态文字色，与边框呼应 */
            font-weight: 500;
            /* 保持非空项的背景色不变 */
        }

        /* 链接标题右侧的序号 */
        /* 标题文本样式 */
        .sidebar-item .title-text {
            flex: 1; /* 占据剩余空间，让序号靠右 */
            margin-left: 0px; /* 与图标保持距离 */
        }

        /* 序号样式 - 靠右对齐 */
        .sidebar-item .title-number {
            color: inherit; /* 继承父元素颜色 */
            opacity: 0.7; /* 稍显弱化，突出主标题 */
            margin-left: 10px; /* 与主标题保持距离 */
            white-space: nowrap; /* 防止序号换行 */
        }

        /* 空项和非空项的序号颜色微调 */
        .sidebar-item:not(.has-content) .title-number {
            color: #6c757d; /* 空项序号颜色稍浅 */
        }

        .sidebar-item.has-content .title-number {
            color: #664d03; /* 非空项序号与背景协调 */
        }

        /* 活动状态下序号高亮 */
        .sidebar-item.active .title-number {
            opacity: 1;
            font-weight: bold;
            color: inherit; /* 继承活动状态的颜色 */
        }
    </style>
    <base target="_self" />
</head>
<body>

<!-- ----------------------------------------------------------------------- -->

<!--顶部导航栏 开始-->
<script src="resources/bootstrap-5.2.0-beta1-dist/js/bootstrap.min.js"></script>
<script src="resources/jQuery/jquery-3.5.1.js"></script>
<span class="fixed-top">
    <?php include "globalNavbar.php"; ?>
</span>
<!--顶部导航栏 结束-->

<!-- ----------------------------------------------------------------------- -->

<!--container 开始-->
<div class="container container mt-3 mb-4">

    <!--一行两列布局 开始-->
    <div class="row">

        <!--左侧分类列表（小屏幕上隐藏） 开始-->
        <nav id="sidebar" class="col-md-3 col-lg-2 bg-light position-fixed sidebar d-none d-sm-none d-md-block collapse" style="z-index: 1000">
            <div class="position-sticky">
                <ul class="sidebar-menu">
                    <?php foreach ($sidebarItems as $item): ?>
                        <li>
                            <span data-targetid="<?php echo $item['id']; ?>"
                                  class="sidebar-item <?php echo $item['empty'] ? '' : 'has-content'; ?>">
                                <i class="bi <?php echo $item['empty'] ? $item['iconEmpty'] . ' icon-empty' : $item['iconFilled'] . ' icon-filled'; ?>"></i>
                                <span class="title-text"><?php echo $item['title']; ?></span>
                                <span class="title-number"><?php echo $item['number']; ?></span>
                            </span>
                        </li>
                    <?php endforeach; ?>
                </ul>
            </div>
        </nav>
        <!--左侧分类列表（小屏幕上隐藏） 结束-->

        <!--右侧待办事项列表 开始-->
        <main class="col-md-9 d-block ms-sm-auto col-lg-9">

            <!-- 站内导航 开始 -->
            <div class="mt-3">
                <nav style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
                    <ol class="breadcrumb">
                        <li class="breadcrumb-item"><a class="text-decoration-none" href="<?php echo $homepage; ?>">首页</a></li>
                        <li class="breadcrumb-item active">每日待办</li>
                    </ol>
                </nav>
            </div>
            <!-- 站内导航 结束 -->

            <!--工具栏 开始-->
            <div class="card">

                <div class="card-header">

                    <div>

                        <?php
                        $days = ["日", "一", "二", "三", "四", "五", "六"];
                        $xingqi = $days[$dayOfWeek];
                        echo <<<BBB
                            <span class="">
                                <span>$specificDateStr | 周{$xingqi} | </span>
                                <span>{$animal}年 | {$monthAndDayLunarChinese} {$jieqi}</span> 
                            </span>
                        BBB;
                        ?>

                    </div>

                    <hr class="mt-1 mb-1" />

                    <div>
                        <?php if ($specificDateStr == $todayStr): ?>
                            <a href="viewByDate.php?date=today" target="_self" class="badge text-bg-danger mx-1 my-1 viewToday">今日</a>
                        <?php else: ?>
                            <a href="viewByDate.php?date=today" target="_self" class="badge text-bg-primary mx-1 my-1 viewToday">今日</a>
                        <?php endif; ?>
                        <a href="viewByDate.php?date=<?php echo $preDayStr; ?>" target="_self" class="badge text-bg-primary mx-1 my-1 viewPreDay">前一日</a>
                        <a href="viewByDate.php?date=<?php echo $nextDayStr; ?>" target="_self" class="badge text-bg-primary mx-1 my-1 viewNextDay">后一日</a>
                        <a href="tasksInSpecific/index.php" target="_self" class="badge text-bg-warning">指定日</a>
                        <span role="button" class="badge text-bg-dark mx-1 my-1 viewInMonth">本月</span>
                        <sapn role="button"
                              data-date="<?php echo $specificDateStr; ?>"
                              class="badge text-bg-dark mx-1 my-1 viewInWeek">本周</sapn>
                        <span>
                    <span role="button" class="badge text-bg-secondary mx-1 my-1 closeAll">折叠</span>
                    <span role="button" class="badge text-bg-secondary mx-1 my-1 openAll">展开</span>
                </span>
                        <?php if ($specificDateObj <= $todayObj): ?>
                            <a href="finished.php?date=<?php echo $specificDateStr; ?>" role="button" class="badge text-bg-info mx-1 my-1 showFinished">已办</a>
                        <?php endif; ?>
                    </div>

                </div>

            </div>
            <!--工具栏 结束-->

            <?php

            // 提示分类卡片内容是否为空的 icon
            $cardHeaderIconEmpty = '<i class="bi bi-calendar-check"></i>';
            $cardHeaderIconNotEmpty = '<i class="bi bi-calendar-check-fill"></i>';

            // 提示分类卡片内容是否为空的卡片标题背景色
            $cardHeaderBGColorEmpty = '';
            $cardHeaderBGColorNotEmpty = 'bg-warning';

            // 卡片内容为空时显示的内容
            $emptyContent = <<<BBB
                <span class="text-muted" style="color: lightgray">
                    <i class="bi bi-box2"></i> 暂无。
                </span>
            BBB;

            $cardHeaderIcon = "";
            $cardHeaderBGColor = "";
            $content = "";

            // -------------------------------------------------------------------------
            // 当日
            // -------------------------------------------------------------------------

            $content = $contents['specificDate'];
            $content = textToHtml($content);

            if (!$content) { // 内容为空
                $cardHeaderIcon = $cardHeaderIconEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorEmpty;
                $content= $emptyContent;
                $contentOfSpecificDateEmpty = true;
            } else { // 内容不为空
                $cardHeaderIcon = $cardHeaderIconNotEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorNotEmpty;
                $contentOfSpecificDateEmpty = false;
            }

            echo <<<BBB
                <span class="col">
                    <div id="specificDate" class="card shadow-sm mt-2">
                        <div role="button" class="card-header d-flex myCardHeader bg-warning {$cardHeaderBGColor}">
                            <div class="w-100 big">
                                {$cardHeaderIcon} 当日
                            </div>
                            <div class="flex-shrink-0" id="btnEditToday">
                                <a role="button" class="badge bg-dark editCurrentDay my-1">编辑(i)</a>
                            </div>
                        </div> 
                        
                        <div class="card-body todoList">
                            {$content}
                        </div>
                    </div>
                </span>
            BBB;

            // -------------------------------------------------------------------------
            // 每年 - 农历
            // -------------------------------------------------------------------------

            $content = $contents['yearlyLunar'];
            $content = textToHtml($content);

            if (!$content) { // 内容为空
                $cardHeaderIcon = $cardHeaderIconEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorEmpty;
                $content = $emptyContent;
                $contentOfYearlyLunarEmpty = true;
            } else { // 内容不为空
                $cardHeaderIcon = $cardHeaderIconNotEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorNotEmpty;
                $contentOfYearlyLunarEmpty = false;
            }

            echo <<<BBB
                <span class="col">
                    <div id="yearlyLunar" class="card shadow-sm mt-2">
                        <div role="button" class="card-header d-flex myCardHeader {$cardHeaderBGColor}">
                            <div class="w-100 big">
                                {$cardHeaderIcon} 农历每年 · {$monthLunarChinese}{$dayOfMonthLunarChinese}
                            </div>
                            <div class="flex-shrink-0">
                                <a data-monthandday="{$monthAndDayLunar}" role="button" class="badge bg-dark editYearlyLunar my-1">编辑(n)</a>
                            </div>
                        </div> 
                        
                        <div class="card-body todoList">
                            {$content}
                        </div>
                    </div>
                </span>
            BBB;

            // -------------------------------------------------------------------------
            // 每月 - 农历
            // -------------------------------------------------------------------------

            $content = $contents['monthlyLunar'];
            $content = textToHtml($content);

            if (!$content) { // 内容为空
                $cardHeaderIcon = $cardHeaderIconEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorEmpty;
                $content = $emptyContent;
                $contentOfMonthlyLunarEmpty = true;
            } else { // 内容不为空
                $cardHeaderIcon = $cardHeaderIconNotEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorNotEmpty;
                $contentOfMonthlyLunarEmpty = false;
            }

            echo <<<BBB
                <span class="col">
                    <div id="monthlyLunar" class="card shadow-sm mt-2">
                        <div role="button" class="card-header d-flex myCardHeader {$cardHeaderBGColor}">
                            <div class="w-100 big">
                                {$cardHeaderIcon} 农历每月 · {$dayOfMonthLunarChinese}
                            </div>
                            <div class="flex-shrink-0">
                                <a role="button" class="badge bg-dark editMonthlyLunarAll my-1">每月(U)</a>
                                <a data-dayofmonth="$dayOfMonthLunar" role="button" class="badge bg-dark editMonthlyLunar my-1">当日(u)</a>
                            </div>
                        </div> 
                        
                        <div class="card-body todoList">
                            {$content}
                        </div>
                    </div>
                </span>
            BBB;

            // -------------------------------------------------------------------------
            // 每年 - 阳历
            // -------------------------------------------------------------------------

            $content = $contents['yearly'];
            $content = textToHtml($content);

            if (!$content) { // 内容为空
                $cardHeaderIcon = $cardHeaderIconEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorEmpty;
                $content = $emptyContent;
                $contentOfYearlyEmpty = true;
            } else { // 内容不为空
                $cardHeaderIcon = $cardHeaderIconNotEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorNotEmpty;
                $contentOfYearlyEmpty = false;
            }

            echo <<<BBB
                <span class="col">
                    <div id="yearly" class="card shadow-sm mt-2">
                        <div role="button" class="card-header d-flex myCardHeader {$cardHeaderBGColor}">
                            <div class="w-100 big">
                                {$cardHeaderIcon} 阳历每年 · {$month}月{$dayOfMonth}号
                            </div>
                            <div class="flex-shrink-0">
                                <a data-monthandday="{$monthAndDay}" role="button" class="badge bg-dark editYearly my-1">编辑(y)</a>
                            </div>
                        </div> 
                        
                        <div class="card-body todoList">
                            {$content}
                        </div>
                    </div>
                </span>
            BBB;

            // -------------------------------------------------------------------------
            // 每月 - 阳历
            // -------------------------------------------------------------------------

            $content = $contents['monthly'];
            $content = textToHtml($content);

            if (!$content) { // 内容为空
                $cardHeaderIcon = $cardHeaderIconEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorEmpty;
                $content = $emptyContent;
                $contentOfMonthlyEmpty = true;
            } else { // 内容不为空
                $cardHeaderIcon = $cardHeaderIconNotEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorNotEmpty;
                $contentOfMonthlyEmpty = false;
            }

            echo <<<BBB
                <span class="col">
                    <div id="monthly" class="card shadow-sm mt-2">
                        <div role="button" class="card-header d-flex myCardHeader {$cardHeaderBGColor}">
                            <div class="w-100 big">
                                {$cardHeaderIcon} 阳历每月 · {$dayOfMonth}号
                            </div>
                            <div class="flex-shrink-0">
                                <a role="button" class="badge bg-dark editMonthlyAll my-1">每月(M)</a>
                                <a data-dayofmonth="$dayOfMonth" role="button" class="badge bg-dark editMonthly my-1">当日(m)</a>
                            </div>
                        </div> 
                        
                        <div class="card-body todoList">
                            {$content}
                        </div>
                    </div>
                </span>
            BBB;

            // -------------------------------------------------------------------------
            // 每周
            // -------------------------------------------------------------------------

            $content = $contents['weekly'];
            $content = textToHtml($content);

            if (!$content) { // 内容为空
                $cardHeaderIcon = $cardHeaderIconEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorEmpty;
                $content = $emptyContent;
                $contentOfWeeklyEmpty = true;
            } else { // 内容不为空
                $cardHeaderIcon = $cardHeaderIconNotEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorNotEmpty;
                $contentOfWeeklyEmpty = false;
            }

            echo <<<BBB
                <span class="col">
                    <div id="weekly" class="card shadow-sm mt-2">
                        <div role="button" class="card-header d-flex myCardHeader {$cardHeaderBGColor}">
                            <div class="w-100 big">
                                {$cardHeaderIcon} 每周 · {$xingqi}
                            </div>
                            <div class="flex-shrink-0">
                                <a role="button" class="badge bg-dark editWeeklyAll my-1">每周(W)</a>
                                <a data-dayofweek="$dayOfWeek" role="button" class="badge bg-dark editWeekly my-1">当日(w)</a>
                            </div>
                        </div> 
                        
                        <div class="card-body todoList">
                            {$content}
                        </div>
                    </div>
                </span>
            BBB;

            // -------------------------------------------------------------------------
            // 每日
            // -------------------------------------------------------------------------

            $content = $contents['daily'];
            $content = textToHtml($content);

            if (!$content) { // 内容为空
                $cardHeaderIcon = $cardHeaderIconEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorEmpty;
                $content = $emptyContent;
                $contentOfDailyEmpty = true;
            } else { // 内容不为空
                $cardHeaderIcon = $cardHeaderIconNotEmpty;
                $cardHeaderBGColor = $cardHeaderBGColorNotEmpty;
                $contentOfDailyEmpty = false;
            }

            echo <<<BBB
                <span class="col">
                    <div id="daily" class="card shadow-sm mt-2">
                        <div role="button" class="card-header d-flex myCardHeader {$cardHeaderBGColor}">
                            <div class="w-100 big">
                                {$cardHeaderIcon} 每日
                            </div>
                            <div class="flex-shrink-0">
                                <a role="button" class="badge bg-dark editDaily my-1">编辑(d)</a>
                            </div>
                        </div> 
                        
                        <div class="card-body todoList">
                            {$content}
                        </div>
                    </div>
                </span>
            BBB;
            ?>

        </main>
        <!--右侧待办事项列表 结束-->

    </div>
    <!--一行两列布局 结束-->

</div>
<!--container 结束-->

<!-- ----------------------------------------------------------------------- -->
<script src="resources/bootstrap-5.2.0-beta1-dist/js/bootstrap.min.js"></script>
<script src="resources/base64/functions.js"></script>
<!-- ----------------------------------------------------------------------- -->

<!--函数定义-->
<script>

    // 从数据库中读取指定日期内的「已完成的事务」
    function readFromFinished(date) {

        var url = "ajax/readFromFinished.php?date=" + date

        $.get({
            url: url,
            async: false
        })
            .done(function( data ) {
                finishedTasksJsonString = data
            })
            .fail(function () {
                alert("请求失败。")
            });

    }

    // 向数据库中写入指定日期内的「已完成的事务」
    function writeToFinished(content, date) {

        var url = "ajax/writeToFinished.php"

        $.post({
            url: url,
            data: {content: content, date: date},
            async: false
        })
            .done(function () {
                console.log("数据写入成功。")
            })
            .fail(function () {
                alert("请求失败。")
            })

    }

    // 检测屏幕宽度（阈值可根据需求调整）
    function isMobileByWidth() {
        const screenWidth = window.screen.width;
        // 假设小于 768px 视为移动设备
        return screenWidth < 768;
    }

    // 平滑滚动页面到指定元素
    function smoothScrollToId(targetId) {
        const targetElement = document.getElementById(targetId);

        if (!targetElement) {
            console.error(`Element with ID "${targetId}" not found`);
            return;
        }

        // 计算偏移后的位置
        const offset = document.querySelector('.fixed-top').offsetHeight; // 固定头部的高度
        const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - offset - 5;

        // 使用原生方法平滑滚动
        window.scrollTo({
            top: targetPosition,
            behavior: 'smooth'
        });
    }

</script>

<!-- ----------------------------------------------------------------------- -->

<!--全局变量-->
<script>
    var finishedTasksJsonString = ""
</script>

<!-- ----------------------------------------------------------------------- -->

<!--网页加载时执行-->
<script>

    readFromFinished("<?php echo $specificDateStr; ?>")

    if (finishedTasksJsonString !== "") {

        // arr string to arr
        finishedTasksJsonString = b64_to_utf8(finishedTasksJsonString)
        var finishedTasks = JSON.parse(finishedTasksJsonString)

        if (finishedTasks.length !== 0) {
            var arr = $(".taskItem")

            for (var item of arr) {
                var taskTitle = $(item).next().text().trim()
                for (var f in finishedTasks) {
                    if (finishedTasks[f] == taskTitle) {
                        $(item).attr("checked", true)
                    }
                }
            }
        }

    }

</script>

<!-- ----------------------------------------------------------------------- -->

<!--事件处理-->
<script>

    $(".closeAll").on("click", function () {
        $(".card-body").slideUp("fast")
    })

    $(".openAll").on("click", function () {
        $(".card-body").slideDown("fast")
    })

    $(".editCurrentDay").on("click", function (e) {
        var url = "edit.php?from=specificDate&date=<?php echo $specificDateStr; ?>"
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editYearly").on("click", function (e) {
        var monthandday = $(this).data("monthandday")
        var url = "edit.php?from=yearly&monthAndDay=" + monthandday
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editYearlyLunar").on("click", function (e) {
        var monthandday = $(this).data("monthandday")
        var url = "edit.php?from=yearlyLunar&monthAndDay=" + monthandday
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editMonthlyAll").on("click", function (e) {
        var url = "repeat/editMonthlyTasks.php"
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editMonthly").on("click", function (e) {
        var dayofmonth = $(this).data("dayofmonth")
        var url = "edit.php?from=monthly&dayOfMonth=" + dayofmonth
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editMonthlyLunarAll").on("click", function (e) {
        var url = "repeat/editMonthlyLunarTasks.php"
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editMonthlyLunar").on("click", function (e) {
        var dayofmonth = $(this).data("dayofmonth")
        var url = "edit.php?from=monthlyLunar&dayOfMonth=" + dayofmonth
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editWeeklyAll").on("click", function (e) {
        var url = "repeat/editWeeklyTasks.php"
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editWeekly").on("click", function (e) {
        var dayofweek = $(this).data("dayofweek")
        var url = "edit.php?from=weekly&dayOfWeek=" + dayofweek
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".editDaily").on("click", function (e) {
        var url = "edit.php?from=daily"
        window.open(url, "_self")
        e.stopPropagation()
    })

    $(".viewInWeek").on("click", function (e) {
        var date = $(this).data("date")
        var url = `tasksInSpecific/weekView.php?from=date&date=${date}`
        window.open(url, "_self")
    })

    $(".viewInMonth").on("click", function (e) {

        var specificDate = "<?php echo $specificDateStr; ?>"

        var year = specificDate.slice(0, 4)
        var month = specificDate.slice(4, 6)

        var url = `tasksInSpecific/monthView.php?year=${year}&month=${month}`
        window.open(url, "_self")

    })

    // 点击「待办事务描述文字」时，点击相应的复选框
    $(".taskTitle").on("click", function () {
        $(this).prev().click()
    })

    // 点击「待办事务描述文字」前面的「复选框」时执行
    $(".taskItem").change(function () {
        // 获取当前选中的任务标题
        const currentTaskTitle = $(this).next().text().trim();
        // 获取当前复选框的状态（选中/未选中）
        const isChecked = $(this).is(':checked');

        // 同步所有同名任务的复选框状态
        $(".taskItem").each(function() {
            const taskTitle = $(this).next().text().trim();
            if (taskTitle === currentTaskTitle) {
                $(this).prop("checked", isChecked);
            }
        });

        // 读取已完成任务列表
        readFromFinished("<?php echo $specificDateStr; ?>");

        let finishedTasks = [];
        if (finishedTasksJsonString !== "") {
            // 解码并解析已完成任务
            finishedTasksJsonString = b64_to_utf8(finishedTasksJsonString);
            finishedTasks = JSON.parse(finishedTasksJsonString);
        }

        if (isChecked) {
            // 如果选中，添加任务（去重）
            if (!finishedTasks.includes(currentTaskTitle)) {
                finishedTasks.push(currentTaskTitle);
            }
        } else {
            // 如果取消选中，移除任务
            const index = finishedTasks.indexOf(currentTaskTitle);
            if (index !== -1) {
                finishedTasks.splice(index, 1);
            }
        }

        // 保存更新后的已完成任务列表
        finishedTasksJsonString = JSON.stringify(finishedTasks);
        finishedTasksJsonString = utf8_to_b64(finishedTasksJsonString);
        writeToFinished(finishedTasksJsonString, "<?php echo $specificDateStr; ?>");
    });


    // 点击卡片标题时，自动折叠或展开卡片内容
    $(".myCardHeader").on("click", function () {
        $(this).next().slideToggle("fast")
    })

    $(".sidebar-item").on("click", function () {
        const targetid = $(this).data("targetid")
        smoothScrollToId(targetid)
    })

    // 侧边栏交互逻辑
    document.addEventListener('DOMContentLoaded', function() {
        const sidebarItems = document.querySelectorAll('.sidebar-item');
        const contentSections = [];

        // 收集所有内容区域的信息
        sidebarItems.forEach(item => {
            const targetId = item.getAttribute('data-targetid');
            const section = document.getElementById(targetId);

            if (section) {
                contentSections.push({
                    id: targetId,
                    element: section,
                    sidebarItem: item
                });
            }
        });

        // 点击侧边栏项时的处理
        sidebarItems.forEach(item => {
            item.addEventListener('click', function() {
                // 移除所有项的活跃状态和可能的背景色样式
                sidebarItems.forEach(i => {
                    i.classList.remove('active');
                    i.style.backgroundColor = ''; // 清除内联背景色
                });
                // 为当前点击项添加活跃状态
                this.classList.add('active');
            });
        });

    });

</script>

<!-- ----------------------------------------------------------------------- -->

<!-- 快捷键-->
<script>

    $(window).keydown(function(event){

        // 查看更多 keycode，参考：
        // https://www.toptal.com/developers/keycode

        // the 快捷键 to 折叠或展开卡片
        // 参考资料：https://stackoverflow.com/questions/93695/best-cross-browser-method-to-capture-ctrls-with-jquery
        if (event.ctrlKey || event.metaKey) {
            switch (event.key) {
                case "ArrowUp":
                    // 按下 Ctrl + ↑ 时折叠所有
                    event.preventDefault();
                    $(".closeAll").click()
                    break;
                case "ArrowDown":
                    // 按下 Ctrl + ↓ 时展开所有
                    event.preventDefault();
                    $(".openAll").click()
            }
        }

        switch (event.key) {
            case "ArrowLeft":
                // 左方向键，查看前一日日程
                $(".viewPreDay")[0].click()
                break
            case "ArrowRight":
                // 右方向键，查看后一日日程
                $(".viewNextDay")[0].click()
                break
            case "0":
                // 数字键 0（包括数字键与小键盘），查看今日日程
                // case "0" 的 引号不可省略
                $(".viewToday")[0].click()
                break
            case "1":
            case "2":
            case "3":
            case "4":
            case "5":
            case "6":
            case "7":
                // 阻止默认行为（如表单输入等）
                event.preventDefault();
                // 计算对应的索引（数字1对应索引0，数字2对应索引1...）
                const index = parseInt(event.key) - 1;
                // 获取侧边栏中对应位置的项目并点击
                const sidebarItems = document.querySelectorAll('.sidebar-item');
                if (sidebarItems[index]) {
                    sidebarItems[index].click();
                }
                break;
            case "i":
            case "I":
                // 编辑当日待办
                $(".editCurrentDay").click()
                break
            case "y":
            case "Y":
                // 编辑每年重复事件
                $(".editYearly").click()
                break
            case "n":
            case "N":
                $(".editYearlyLunar").click()
                break;
            case "M":
                // 编辑每月所有重复事件
                $(".editMonthlyAll").click()
                break;
            case "m":
                // 编辑每月当天重复事件
                $(".editMonthly").click()
                break
            case "U":
                // 编辑农历每月所有重复事件
                $(".editMonthlyLunarAll").click()
                break;
            case "u":
                // 编辑农历每月当天重复事件
                $(".editMonthlyLunar").click()
                break
            case "W":
                // 编辑每周所有重复事件
                $(".editWeeklyAll").click()
                break;
            case "w":
                // 编辑每周当天重复事件
                $(".editWeekly").click()
                break
            case "d":
            case "D":
                // 编辑每日重复事件
                if (event.altKey !== true) {
                    $(".editDaily").click()
                }
                break
            case "l":
            case "L":
                $(".floating-btn").click()
                break;
            default:
                // pass
                break;
        }

    })

</script>

<!-- ----------------------------------------------------------------------- -->

<!-- 模拟 vim 快捷键 j, k, gg, G -->
<script>
    // 存储快捷键状态
    const shortcutState = {
        lastGTime: 0,       // 记录上次按g键的时间
        gPressed: false,    // g键是否被按下
        timeout: null       // 用于处理快捷键超时
    };

    // 滚动配置
    const scrollConfig = {
        step: 150,           // 每次j/k滚动的像素数
        timeout: 300        // 双击g键的超时时间(毫秒)
    };

    // 处理键盘事件
    document.addEventListener('keydown', (e) => {
        // 当在输入框中时不触发快捷键
        if (['INPUT', 'TEXTAREA', 'SELECT'].includes(e.target.tagName) ||
            e.target.isContentEditable) {
            return;
        }

        const key = e.key.toLowerCase();

        // 处理j键 - 向下滚动
        if (key === 'j') {
            e.preventDefault();
            window.scrollBy({
                top: scrollConfig.step,
                behavior: 'smooth'
            });
        }

        // 处理k键 - 向上滚动
        else if (key === 'k') {
            e.preventDefault();
            window.scrollBy({
                top: -scrollConfig.step,
                behavior: 'smooth'
            });
        }

        // 处理G键(大写) - 滚动到底部
        else if (key === 'g' && e.shiftKey) {
            e.preventDefault();
            window.scrollTo({
                top: document.body.scrollHeight,
                behavior: 'smooth'
            });
        }

        // 处理g键 - 可能是gg组合的一部分
        else if (key === 'g' && !e.shiftKey) {
            e.preventDefault();

            // 如果已经按过一次g键
            if (shortcutState.gPressed) {
                const currentTime = Date.now();
                // 检查两次按g的时间间隔是否在超时时间内
                if (currentTime - shortcutState.lastGTime < scrollConfig.timeout) {
                    // 滚动到顶部
                    window.scrollTo({
                        top: 0,
                        behavior: 'smooth'
                    });
                }
                // 重置状态
                resetGState();
            }
            // 第一次按g键
            else {
                shortcutState.gPressed = true;
                shortcutState.lastGTime = Date.now();

                // 设置超时，超过时间未按第二次则重置状态
                shortcutState.timeout = setTimeout(resetGState, scrollConfig.timeout);
            }
        }
    });

    // 重置g键状态
    function resetGState() {
        shortcutState.gPressed = false;
        shortcutState.lastGTime = 0;
        if (shortcutState.timeout) {
            clearTimeout(shortcutState.timeout);
            shortcutState.timeout = null;
        }
    }
</script>

<!-- ----------------------------------------------------------------------- -->

<!-- 添加「返回顶部按钮」 -->
<script src="resources/vanilla-back-to-top/index.js"></script>
<script src="resources/vanilla-back-to-top/config.js"></script>

<!-- ----------------------------------------------------------------------- -->

<!--添加悬浮菜单按钮-->
<script src="resources/floatingMenu.js"></script>
<script>

    const options = {
        // 核心配置：指定屏幕宽度小于等于768px时显示
        maxScreenWidth: 768,

        // 自定义按钮样式
        buttonColor: '#28a745',     // 按钮颜色（Bootstrap success绿色）
        buttonSize: 56,             // 按钮尺寸

        positionFrom: 'top',        // 按钮定位基准：'top'（顶部）或 'bottom'（底部）

        menuTitle: '待办分类',       // 菜单标题文本（可自定义）
        // 自定义菜单项
        menuItems: [
            { text: '当日', targetId: 'specificDate', isEmpty: <?php echo $contentOfSpecificDateEmpty ? "true" : "false"; ?> },
            { text: '农历每年', targetId: 'yearlyLunar', isEmpty: <?php echo $contentOfYearlyLunarEmpty ? "true" : "false"; ?>},
            { text: '农历每月', targetId: 'monthlyLunar', isEmpty: <?php echo $contentOfMonthlyLunarEmpty ? "true" : "false"; ?>},
            { text: '阳历每年', targetId: 'yearly', isEmpty: <?php echo $contentOfYearlyEmpty ? "true" : "false"; ?>},
            { text: '阳历每月', targetId: 'monthly', isEmpty: <?php echo $contentOfMonthlyEmpty ? "true" : "false"; ?>},
            { text: '每周', targetId: 'weekly', isEmpty: <?php echo $contentOfWeeklyEmpty ? "true" : "false"; ?>},
            { text: '每日', targetId: 'daily', isEmpty: <?php echo $contentOfDailyEmpty ? "true" : "false"; ?>}
        ],

        // 自定义滚动行为
        scrollOptions: {
            duration: 600,            // 滚动动画时长
            easing: 'easeOutQuad'     // 滚动动画类型
        }
    }

    // 初始化悬浮菜单
    FloatingMenu.init(options);
</script>

<!-- ----------------------------------------------------------------------- -->

</body>
</html>
